package com.sophossystems.client.asmon.dao.spring;

import com.sophossystems.client.asmon.dao.ActivityDao;
import com.sophossystems.client.asmon.dto.ActivityDTO;
import com.sophossystems.client.asmon.dto.ActivityPkDTO;
import com.sophossystems.client.asmon.exceptions.DaoException;
import com.sophossystems.client.asmon.hibernate.Activity;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.Query;

import org.hibernate.transform.Transformers;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.transaction.annotation.Transactional;

public class ActivityDaoImpl extends AbstractDAO implements ActivityDao {

	/**
	 * Method 'insert'
	 * 
	 * @param dto
	 * @return ActivityPk
	 */
	private static Logger log = Logger.getLogger(ActivityDaoImpl.class);

	@Override
	@Transactional
	public ActivityPkDTO insert(final ActivityDTO dto) {
		ActivityPkDTO exito = null;
		try {
			exito = (ActivityPkDTO) getHibernateTemplate().execute(
					new HibernateCallback() {
						/**
						 * {@inheritDoc}
						 * 
						 * @see org.springframework.orm.hibernate3.HibernateCallback#doInHibernate(org.hibernate.Session)
						 */
						@Override
						public Object doInHibernate(Session session)
								throws HibernateException, SQLException {
							Transaction tx = session.beginTransaction();
							ActivityPkDTO pk = null;
							Activity activity = new Activity();
							activity.mapper(dto);
							session.save(activity);
							log.debug("El insert de actividad: "
									+ dto.getDescription() + " Module: "
									+ dto.getIdModule());
							System.out.println("El insert de actividad: "
									+ dto.getDescription() + " Module: "
									+ dto.getIdModule());
							tx.commit();
							try {
								ActivityDTO res = findWhereDescriptionEquals(
										dto.getDescription()).get(0);
								pk = new ActivityPkDTO();
								pk.setIdActivity(res.getIdActivity());
							} catch (DaoException es) {

								throw new HibernateException("Insersion: "
										+ es.getMessage());
							}
							return pk;
						}

					});

		} catch (final Exception e) {
			logger.error("Error: getActivity, cause: " + e.getMessage(), e);

		}
		return exito;
	}

	/**
	 * Updates a single row in the Activity table.
	 */
	@Override
	@Transactional
	public void update(final ActivityDTO dto) throws DaoException {
		try {
			getHibernateTemplate().execute(new HibernateCallback() {
				/**
				 * {@inheritDoc}
				 * 
				 * @see org.springframework.orm.hibernate3.HibernateCallback#doInHibernate(org.hibernate.Session)
				 */
				@Override
				public Object doInHibernate(Session session)
						throws HibernateException, SQLException {
					ActivityPkDTO aPk = null;
					ActivityDTO res = null;
					Transaction tx = session.beginTransaction();
					// Aqui primero se busca si existe el registro
					try {
						res = findByPrimaryKey(dto
								.getIdActivity());
						aPk = new ActivityPkDTO();
						aPk.setIdActivity(res.getIdActivity());
					} catch (DaoException es) {
						throw new HibernateException("Update ActivityDao: "
								+ es.getMessage());
					}
					// /aqui se actualizar los campos y con los de la entrada
					// cuidado de actualiza todo.
					Activity persis = new Activity();
					persis.mapper(dto);
					persis.setIdActivity(res.getIdActivity());
					session.update(persis);
					tx.commit();
					return null;
				}
			});
		} catch (final Exception e) {
			logger.error("Error: getActivity, cause: " + e.getMessage(), e);
			throw new DaoException("Error: getActivity, cause: "
					+ e.getMessage());
		}

	}

	/**
	 * Deletes a single row in the Activity table.
	 */
	@Override
	@Transactional
	public void delete(final ActivityPkDTO pk) throws DaoException {

		try {
			getHibernateTemplate().execute(new HibernateCallback() {
				/**
				 * {@inheritDoc}
				 * 
				 * @see org.springframework.orm.hibernate3.HibernateCallback#doInHibernate(org.hibernate.Session)
				 */
				@Override
				public Object doInHibernate(Session session)
						throws HibernateException, SQLException {
					Transaction tx = session.beginTransaction();
					Activity activity = (Activity) session.load(Activity.class,
							pk.getIdActivity());
					session.delete(activity);
					tx.commit();
					return null;
				}
			});
		} catch (final Exception e) {
			logger.error("Error: getActivity, cause: " + e.getMessage(), e);
			throw new DaoException("Error: getActivity, cause: "
					+ e.getMessage());
		}
	}

	/**
	 * Method 'getTableName'
	 * 
	 * @return String
	 */
	public String getTableName() {
		return "Activity";
	}

	/**
	 * Returns all rows from the Activity table that match the criteria
	 * 'idActivity = :idActivity'.
	 */
	@Override
	@Transactional
	public ActivityDTO findByPrimaryKey(final int idActivity)
			throws DaoException {
		ActivityDTO actividad = null;
		try {
			actividad = (ActivityDTO) getHibernateTemplate().execute(
					new HibernateCallback() {
						/**
						 * {@inheritDoc}
						 * 
						 * @see org.springframework.orm.hibernate3.HibernateCallback#doInHibernate(org.hibernate.Session)
						 */
						@Override
						public Object doInHibernate(Session session)
								throws HibernateException, SQLException {
							final Query oQuery = session
									.createQuery("SELECT a.idActivity as idActivity, a.description as description,"
											+ " a.idModule as idModule FROM "
											+ getTableName()
											+ " a WHERE a.idActivity = :idActivity");

							oQuery.setInteger("idActivity", idActivity);

							ActivityDTO actividaddto = (ActivityDTO) oQuery
									.setResultTransformer(
											Transformers
													.aliasToBean(ActivityDTO.class))
									.list().get(0);

							return actividaddto;
						}
					});
		} catch (final Exception e) {
			logger.error("Error: getActivity, cause: " + e.getMessage(), e);
			throw new DaoException("Error: getActivity, cause: "
					+ e.getMessage());
		}
		return actividad;

	}

	/**
	 * Returns all rows from the Activity table that match the criteria ''.
	 */
	@Override
	@Transactional
	@SuppressWarnings("unchecked")
	public List<ActivityDTO> findAll() throws DaoException {
		List<ActivityDTO> actividad = null;
		try {
			actividad = (List<ActivityDTO>) getHibernateTemplate().execute(
					new HibernateCallback() {
						/**
						 * {@inheritDoc}
						 * 
						 * @see org.springframework.orm.hibernate3.HibernateCallback#doInHibernate(org.hibernate.Session)
						 */
						@Override
						public Object doInHibernate(Session session)
								throws HibernateException, SQLException {
							final Query oQuery = session
									.createQuery("SELECT a.idActivity as idActivity, a.description as description, a.idModule as idModule FROM "
											+ getTableName()
											+ " a ORDER BY a.idActivity");
							List<ActivityDTO> actividaddto = oQuery
									.setResultTransformer(
											Transformers
													.aliasToBean(ActivityDTO.class))
									.list();

							return actividaddto;
						}
					});
		} catch (final Exception e) {
			logger.error("Error: getActivity, cause: " + e.getMessage(), e);
			throw new DaoException("Error: getActivity, cause: "
					+ e.getMessage());
		}
		return actividad;
	}

	/**
	 * Returns all rows from the Activity table that match the criteria
	 * 'idActivity = :idActivity'.
	 */
	@Override
	@Transactional
	public List<ActivityDTO> findWhereIdActivityEquals(int idActivity) {
		List<ActivityDTO> lista = null;
		try {
			lista = new ArrayList<ActivityDTO>();
			lista.add(this.findByPrimaryKey(idActivity));
		
			return lista;
		} catch (Exception es) {
			log.debug("Error en el findWhereIdActivityEquals");
		}
		return lista;

	}

	/**
	 * Returns all rows from the Activity table that match the criteria
	 * 'description = :description'.
	 */
	@Override
	@Transactional
	@SuppressWarnings("unchecked")
	public List<ActivityDTO> findWhereDescriptionEquals(final String description)
			throws DaoException {

		List<ActivityDTO> actividad = null;
		try {
			actividad = (List<ActivityDTO>) getHibernateTemplate().execute(
					new HibernateCallback() {
						/**
						 * {@inheritDoc}
						 * 
						 * @see org.springframework.orm.hibernate3.HibernateCallback#doInHibernate(org.hibernate.Session)
						 */
						@Override
						public Object doInHibernate(Session session)
								throws HibernateException, SQLException {
							final Query oQuery = session
									.createQuery("SELECT a.idActivity as idActivity, a.description as description, a.idModule as idModule FROM "
											+ getTableName()
											+ " a WHERE a.description = :description ORDER BY a.description");
							oQuery.setString("description", description);
							List<ActivityDTO> actividaddto = oQuery
									.setResultTransformer(
											Transformers
													.aliasToBean(ActivityDTO.class))
									.list();
							log.debug("Se obtuvo el resultado: "
									+ actividaddto.size());
							return actividaddto;
						}
					});
		} catch (final Exception e) {
			logger.error("Error: getActivity, cause: " + e.getMessage(), e);
			throw new DaoException("Error: getActivity, cause: "
					+ e.getMessage());
		}
		return actividad;

	}

	/**
	 * Returns all rows from the Activity table that match the criteria
	 * 'idModule = :idModule'.
	 */
	@Override
	@Transactional
	@SuppressWarnings("unchecked")
	public List<ActivityDTO> findWhereIdModuleEquals(final int idModule)
			throws DaoException {

		List<ActivityDTO> actividad = null;
		try {
			actividad = (List<ActivityDTO>) getHibernateTemplate().execute(
					new HibernateCallback() {
						/**
						 * {@inheritDoc}
						 * 
						 * @see org.springframework.orm.hibernate3.HibernateCallback#doInHibernate(org.hibernate.Session)
						 */
						@Override
						public Object doInHibernate(Session session)
								throws HibernateException, SQLException {
							final Query oQuery = session
									.createQuery("SELECT a.idActivity as idActivity, a.description as description, a.idModule as idModule FROM "
											+ getTableName()
											+ " a WHERE a.idModule = :Module ORDER BY a.idModule");
							oQuery.setInteger("Module", idModule);
							List<ActivityDTO> actividaddto = oQuery
									.setResultTransformer(
											Transformers
													.aliasToBean(ActivityDTO.class))
									.list();

							return actividaddto;
						}
					});
		} catch (final Exception e) {
			logger.error("Error: getActivity, cause: " + e.getMessage(), e);
			throw new DaoException("Error: getActivity, cause: "
					+ e.getMessage());
		}
		return actividad;
	}

	/**
	 * Returns the rows from the Activity table that matches the specified
	 * primary-key value.
	 */
	@Override
	public ActivityDTO findByPrimaryKey(ActivityPkDTO pk) throws DaoException {
		return findByPrimaryKey(pk.getIdActivity());
	}

	@Override
	public ActivityPkDTO findLastInsert() throws DaoException {
		ActivityPkDTO activity = null;
		try {
			activity = (ActivityPkDTO) getHibernateTemplate().execute(
					new HibernateCallback() {

						@Override
						public Object doInHibernate(Session session)
								throws HibernateException, SQLException {
							
							Query oQuery = session
									.createQuery("SELECT max(a.idActivity) as idActivity FROM "
											+ getTableName()
											+ " a ");
							
							ActivityPkDTO activityDto = (ActivityPkDTO) oQuery
									.setResultTransformer(Transformers
											.aliasToBean(ActivityPkDTO.class)).list().get(0);
							return activityDto;
						}
					});
		
		} catch (Exception e) {
			logger.error("Error: Activity, cause: " + e.getMessage(), e);
			throw new DaoException("Query failed", e);
		}
		return activity;

	}
	
}
